from decimal import Decimal

from django.shortcuts import render
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
# Create your views here.
from carts.serializers import GWCSerializers, GWCModelSerializer, GWCDeleteSerializer, GWCSelectSerialize, \
    OrderSettlementSerialize
from django_redis import get_redis_connection

from rest_framework.response import Response

from goods.models import SKU


class GWCView(APIView):
    """
    购物车增删改查
    """
    permission_classes = (IsAuthenticated,)
    def post(self,request):
        """
        添加购物车数据
        :param request:
        检验数据 sku_id,count--- 给序列化器进行检验
        保存数据： Redis中： 购物车数据-- 哈希 ，购物车勾选数据--集合
        :return:
        """
        ser = GWCSerializers(data=request.data)
        ser.is_valid(raise_exception=True)
        # 获取 验证通过后的数据
        sku_id = ser.validated_data.get('sku_id')
        count =  ser.validated_data.get('count')
        selected =  ser.validated_data.get('selected')
        # 保存数据
        #  获取当前登录的用户
        user =  request.user
        # user.is_authenticated   验证用户是否认证通过
        if user and user.is_authenticated:
            # 添加数据到Redis中
            redis_conn = get_redis_connection('cart')
            pl =  redis_conn.pipeline()
            # 购物车数据
            pl.hincrby('cart_%d' % user.id,sku_id,count)
            # 购物车勾选数据
            if selected == False:
                # 执行删除勾选的商品
                pl.srem('selected_%d' % user.id,sku_id)
                pl.execute()
            else:
                #  添加勾选商品
                pl.sadd('selected_%d' % user.id,sku_id)
                pl.execute()
            pl.execute()

        # 返回数据
        return Response(ser.data,status=201)

    def get(self,request):
        user =  request.user
        if user and user.is_authenticated:
            redis_conn = get_redis_connection('cart')
            #  购物车中的商品id,数量 hgetall 获取所有的值
            cart_sku_id =  redis_conn.hgetall('cart_%d' % user.id)
            print(cart_sku_id)
            #  购物车中勾选的商品id
            selected_id =  redis_conn.smembers('selected_%d' % user.id)
            print(selected_id)
            cart_dict = {}  # {8: {'count': 1, 'selected': True}}
            for sku_id_bytes,count_bytes in cart_sku_id.items():
                cart_dict[int(sku_id_bytes)] ={
                    'count':int(count_bytes),
                    'selected': sku_id_bytes in selected_id
                }
            print(cart_dict)
            # 查询模型类数据
            sku_ids =  cart_dict.keys()
            skus =  SKU.objects.filter(id__in = sku_ids)
            #把商品的数量，勾选 添加到这个查询对象中
            for sku in skus:
                sku.count =  cart_dict[sku.id]['count']
                sku.selected =  cart_dict[sku.id]['selected']
            #  序列化数据
            ser =  GWCModelSerializer(skus,many=True)
            return Response(ser.data)

    def put(self,request):
        """
        购物车修改功能
        检验一下前端发送过来的数据是否存在，是否类型一致

        """
        user = request.user
        # request.data 获取数据，交给序列化器 GWCSerializers
        ser =  GWCSerializers(data=request.data)
        ser.is_valid(raise_exception=True)
        #  获取验证通过后的数据
        sku_id =  ser.validated_data.get('sku_id')
        count =  ser.validated_data.get('count')
        selected = ser.validated_data.get('selected')
        if user and user.is_authenticated:
            #  修改购物车商品数据 -- 直接覆盖原来添加的商品数量
            redis_con = get_redis_connection('cart')
            pl =  redis_con.pipeline()
            #  修改购物车数据
            pl.hset('cart_%d'% user.id,sku_id,count)
            #  购物车勾选数据
            if selected == False:
                # 执行删除勾选的商品
                pl.srem('selected_%d' % user.id,sku_id)
                pl.execute()
            else:
                #  添加勾选商品
                pl.sadd('selected_%d' % user.id,sku_id)
                pl.execute()
            pl.execute()

        return Response(ser.data)
    # GWCDeleteSerializer
    def delete(self,request):
        ser =  GWCDeleteSerializer(data=request.data)
        ser.is_valid(raise_exception=True)
        sku_id =  ser.validated_data.get('sku_id')
        user =  request.user
        if user and user.is_authenticated:
            redis_con = get_redis_connection('cart')
            pl = redis_con.pipeline()
            # 删除 购物车数据 --哈希
            pl.hdel('cart_%d' % user.id,sku_id)
            #  删除购物车勾选数据
            pl.srem('selected_%d' % user.id,sku_id)
            # 执行管道命令
            pl.execute()
        return Response(status=204)



class GWCSelectAllView(APIView):
    """
    购物车全选

    """
    def put(self,request):
        # GWCSelectSerialize
        ser =  GWCSelectSerialize(data=request.data)
        ser.is_valid(raise_exception=True)

        user = request.user
        selected =  ser.validated_data.get('selected')

        if user and user.is_authenticated:
            #  修改购物车勾选数据 --
            redis_con = get_redis_connection('cart')
            pl =  redis_con.pipeline()
            cart_dict =  redis_con.hgetall('cart_%d' % user.id)
            sku_ids =cart_dict.keys()
            print(sku_ids)
            if selected ==True:
                pl.sadd('selected_%d' % user.id,*sku_ids)
                pl.execute()
            else:
                pl.srem('selected_%d' % user.id, *sku_ids)
                pl.execute()


        return Response(ser.data)

class OrderSettlement(APIView):
    """
    订单结算页功能查询
    """

    def get(self,request):
        user = request.user

        #  查询Redis中勾选的商品id（sku_id）
        redis_conn  = get_redis_connection('cart')
        #  勾选的数据  只能返回 商品的ID 商品的数量怎么办呀？所以我们还得从哈希里面获取数量
        cart_selected =  redis_conn.smembers('selected_%d' % user.id)

        cart_dict= redis_conn.hgetall('cart_%d' % user.id)
        # sku_id ,count
        carts =  {}  # {sku_id:count}
        for  sku_id in  cart_selected:
            carts[int(sku_id)] = int(cart_dict[sku_id])
        # 查询商品信息数据
        skus = SKU.objects.filter(id__in=carts.keys())
        #  循环 出查询的商品数据 给他添加商品数量属性
        for sku in skus:
            sku.count = carts[sku.id]
        freight = Decimal('10.00')
        ser =  OrderSettlementSerialize({'skus':skus,'freight':freight})
        return Response(ser.data)